----------------------
-- Enemies
----------------------
Enemy = {}
Enemy.__index = Enemy

function Enemy.new(type, initial_x, initial_y, area_w, area_h)
    local g = {}
    setmetatable(g, Enemy)
    
    -- constants
    g.FREEZE_TIME = 0.5
    
    -- variables
    g.c_type = "enemy"
    g.state = "alive"
    g.vel_x = 0.0
    g.vel_y = 0.0
    g.hp = 5.0
    g.maxHp = 5.0
    g.sleep_time = 0.0
    g.bounding_box = Rectangle.new(0, 0, 0, 0)
    g.offset = Point.new(0.0, 0.0)
    g.do_not_move_time = 0.0
    g.area_w = area_w
    g.area_h = area_h
    
    -- states and stuff
    g.idle_time = 0.0
    g.elapsed_time = 0.0
    g.speed_x = 0
    g.speed_y = 0
    
    -- particles
    g.ko_effect = nil
    g.hit_effect = nil
    g:initKoParticleSystem()
    g:initHitParticleSystem()
    
    -- sprite and animations
    g.type = type
    g.sprite = Sprite.new()
    
    -- Create different type of enemies
    local y_fix = 0 -- for lifting enemy a littile from ininital place, usually it is bounding_box.height
    if type == "giantbeetle" then
        g.sprite:loadImage("beetle", "content/enemies/giant-beetle.png")
        g.sprite:addAnimation("walking", "beetle", 120, 54, {0, 1, 2, 3, 4, 5}, 0.1, true)
        g.bounding_box:set(0, 0, 100, 40)
        y_fix = 40
    end
    
    if type == "rat" then
        g.sprite:loadImage("rat", "content/enemies/rat.png")
        g.sprite:setOrigin(39, 0)
        g.bounding_box:set(0, 0, 20, 15) -- 68, 20
        g.offset:set(-10, 5.0)
        y_fix = 15
    end
    
    -- positions
    g.initial_x = initial_x
    g.initial_y = initial_y - y_fix
    g.x = g.initial_x
    g.y = g.initial_y
    
    return g
end

-- init
function Enemy:init()
    self.state = "alive"
    self.hp = self.maxHp
    self.x = self.initial_x
    self.y = self.initial_y
    self.sprite:stopFlickering()
end

-- init ko_effect particle system
function Enemy:initKoParticleSystem()
    local sprite = Sprite.new()
    sprite:loadImage("ef", "content/particles/effect.png")
    
    self.ko_effect = love.graphics.newParticleSystem(sprite:getCurrentImage(), 15)
    self.ko_effect:setLifetime(1.0)
	self.ko_effect:setParticleLife(1.0)
   	self.ko_effect:setEmissionRate(100)
   	self.ko_effect:setDirection(math.pi * 2)
   	self.ko_effect:setSpeed(30, 50)
   	self.ko_effect:setSpread(math.pi * 2)
	self.ko_effect:setRotation(-math.pi, math.pi)
	self.ko_effect:setTangentialAcceleration(50, 100)
	self.ko_effect:setColor(255, 255, 255, 255, 255, 255, 255, 0)
    self.ko_effect:setSize(1.0, 2.0, 1)
end

-- init hit_effect particle system
function Enemy:initHitParticleSystem()
    local sprite = Sprite.new()
    sprite:loadImage("ef", "content/particles/hitEffect.png")
    
    self.hit_effect = love.graphics.newParticleSystem(sprite:getCurrentImage(), 10)
    self.hit_effect:setLifetime(0.25)
	self.hit_effect:setParticleLife(0.25)
   	self.hit_effect:setEmissionRate(100)
   	self.hit_effect:setDirection(math.pi * 2)
    self.hit_effect:setRotation(0, math.pi * 2)    
	self.hit_effect:setColor(255, 255, 255, 255, 255, 255, 255, 0)
end

-- damage that player is taken after hit
function Enemy:getDamage()
    return 25
end

-- hit
function Enemy:hit()
	self.sleep_time = 0.1
end

-- takes hit when touching player's shield
function Enemy:takeShieldHit()
    self.do_not_move_time = self.FREEZE_TIME
end

-- take hit, returns true if HP is below 0
function Enemy:takeHit(damage, pos_x, pos_y)
    -- take damage
    self.hp = self.hp - damage
    self.sprite:playFlickering(0.2, 0.2)
    self.do_not_move_time = self.FREEZE_TIME
    
    -- hit particles
    self.hit_effect:setPosition(pos_x, pos_y)
    if not self.hit_effect:isActive() then
        self.hit_effect:start()
    else
        self.hit_effect:reset()
    end
    
    -- if enemy is dead
    if self.hp <= 0 then
        self.state = "dead"
        
        -- particles
        self.ko_effect:setPosition(self.bounding_box:centerX(), self.bounding_box:top())
        self.ko_effect:start()
        
        return true
    end
    
    return false
end

-- can take hit
function Enemy:canTakeHit()
	return (not self.sprite.is_hit and self.sleep_time <= 0.0)
end

-- bounding box update
function Enemy:updateBoundingBox()
    self.bounding_box.x = self.x
    self.bounding_box.y = self.y
end

-- update AI, it takes account player's actions
function Enemy:updateAI(player)
    if self.do_not_move_time >= 0.0 then
        self.do_not_move_time = self.do_not_move_time - global_delta_time
        return
    end

    -- basic stuff
    local distance_x = math.abs(player.x - self.x)
    local distance_y = math.abs(player.y - self.y)
    local should_use_facing = false
    
    if self.type == "rat" then
        if distance_x < 100 and player.on_ground then
            --self.x = linearInterp(self.x, player.x, 0.05)
            if player.x < self.x then
                self.x = self.x - 1
            else
                self.x = self.x + 1
            end
            
            should_use_facing = true
        end
    end
    
    -- flipping :)
    if should_use_facing then
        if player.x + player.bounding_box:centerX() < self.x + self.bounding_box:centerX() then
            self.sprite:flip(false, false)
        else
            self.sprite:flip(true, false)
        end
    end
end

-- update
function Enemy:update()
    -- update particles
    self.ko_effect:update(global_delta_time)
    self.hit_effect:update(global_delta_time)

    if self.state == "dead" then return end
	if self.sleep_time > 0.0 then
		self.sleep_time = self.sleep_time - global_delta_time
		return
	end

    self:updateBoundingBox()
    self.sprite:update()
end

-- draw
function Enemy:draw(camera)
    if self.state ~= "dead" then
        --local b = self.bounding_box
        --love.graphics.rectangle("fill", camera:getRenderX(b.x), camera:getRenderY(b.y), b.width, b.height)
        
        local x = self.x - self.offset.x
        local y = self.y - self.offset.y
        
        if camera ~= nil then
            x = camera:getRenderX(x)
            y = camera:getRenderY(y)
        end

        self.sprite:draw(x, y)
    end
end

-- draw effecst
function Enemy:drawEffects(camera)
    -- draw particles    
    love.graphics.draw(self.hit_effect, -camera.x, -camera.y)
    love.graphics.draw(self.ko_effect, -camera.x, -camera.y)
end
